#include "base.h"
#include "mycoroutine_coroutine.h"

static int mycoroInit = 0;

void cg_init(){
	if(!mycoroInit){
		mycoroInit = 1;

		coroG.last_cid = 0;
		coroG.current = NULL;
		coroG.coroutines.corosize = 0;
		coroG.user_yield_coros.corosize = 0;
		Coroutine_array_init(&coroG.coroutines);

		coroG.on_yield = PHPCoroutine_on_yield;
		coroG.on_resume = PHPCoroutine_on_resume;
	}
}

void cg_dest(){
	mycoroInit = 0;
	free(coroG.coroutines.coroutines);
	free(coroG.user_yield_coros.coroutines);
}

void Coroutine_array_init(coroArray *ca){
	ca->coroutines = (Coroutine **)malloc(CORO_SIZE * sizeof(Coroutine *));
	if(!ca->coroutines){
		printf("malloc error\n");
		exit(-1);
	}

	ca->corosize = CORO_SIZE;
}

long Coroutine_array_push(Coroutine *co){
	long cid = coroG.last_cid;

	if(cid >= coroG.coroutines.corosize){
		coroG.coroutines.coroutines = (Coroutine **)realloc(coroG.coroutines.coroutines,(coroG.coroutines.corosize + CORO_SIZE) * sizeof(Coroutine *));
		if(!coroG.coroutines.coroutines){
			printf("realloc error\n");
			exit(-1);
		}
		coroG.coroutines.corosize += CORO_SIZE;
	}

	coroG.coroutines.coroutines[cid] = co;
	coroG.last_cid++;

	return cid;
}

void Coroutine_array_insert(long cid,Coroutine *coro){
	long size = coroG.user_yield_coros.corosize;
	while(cid >= size){
		size += CORO_SIZE;
	}

	coroG.user_yield_coros.coroutines = (Coroutine **)realloc(coroG.user_yield_coros.coroutines,size * sizeof(Coroutine *));
	if(!coroG.user_yield_coros.coroutines){
		printf("realloc error\n");
		exit(-1);
	}

	coroG.user_yield_coros.corosize = size;
	coroG.user_yield_coros.coroutines[cid] = coro;
}

Coroutine* Coroutine_array_find(coroArray *coa,long cid){
	if(cid >= coa->corosize){
		return NULL;
	}

	return coa->coroutines[cid];
}

void Coroutine_array_erase(Coroutine **cos,long cid){
	cos[cid] = NULL;
}

Coroutine *get_current(){
	return coroG.current;
}
